package com.fp.m7.client.presenter;

import net.customware.gwt.presenter.client.EventBus;
import net.customware.gwt.presenter.client.place.PlaceRequest;
import net.customware.gwt.presenter.client.place.PlaceRequestEvent;
import net.customware.gwt.presenter.client.widget.WidgetDisplay;
import net.customware.gwt.presenter.client.widget.WidgetPresenter;

import com.allen_sauer.gwt.log.client.Log;
import com.fp.m7.client.MyMessages;
import com.fp.m7.client.common.IValidatableDisplay;
import com.fp.m7.client.event.InfoEvent;
import com.fp.m7.client.place.LoginPlace;
import com.fp.m7.shared.Constants;
import com.fp.m7.shared.ValidationResult;
import com.fp.m7.shared.services.AccountServiceAsync;
import com.fp.m7.shared.validator.RegistrationValidator;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasText;
import com.google.inject.Inject;

/**
 * Register presenters speaks for itself :). Its display has some validation methods to display errors.
 * 
 * @author 7
 */
public class RegisterPresenter extends WidgetPresenter<RegisterPresenter.Display> {

    public interface Display extends WidgetDisplay, IValidatableDisplay {

        void setCaptchaUrl(String url);

        HasText getUsername();

        HasText getPassword();

        HasText getPasswordRepeated();

        HasText getNickname();

        HasText getCaptchaText();

        HasClickHandlers getSubmitButton();

        void clearPasswords();

        void clear();

    }

    private static MyMessages msg = GWT.create(MyMessages.class);

    private AccountServiceAsync accountService;
    private RegistrationValidator validator;

    @Inject
    public RegisterPresenter(Display display, EventBus eventBus, //
            RegistrationValidator validator, //
            AccountServiceAsync accountService) {

        super(display, eventBus);

        this.validator = validator;
        this.accountService = accountService;
    }

    @Override
    protected void onBind() {
        display.setCaptchaUrl(Constants.CAPTCHA_URL);

        display.getSubmitButton().addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent paramClickEvent) {
                String username = display.getUsername().getText();
                String nickname = display.getNickname().getText();
                String password = display.getPassword().getText();
                String passwordRepeated = display.getPasswordRepeated().getText();
                String captchaText = display.getCaptchaText().getText();

                ValidationResult result = validator.validate(username, nickname, password, passwordRepeated);

                display.clearPasswords();
                display.showErrors(result);

                if (result.isOk()) {
                    accountService.newAccount(username, password, nickname, captchaText, registerAccountCallback);
                }
            }
        });
    }

    @Override
    protected void onUnbind() {
    }

    @Override
    protected void onRevealDisplay() {
        display.clear();
    }

    private AsyncCallback<ValidationResult> registerAccountCallback = new AsyncCallback<ValidationResult>() {
        @Override
        public void onSuccess(ValidationResult result) {
            display.showErrors(result);
            if (result.isOk()) {
                eventBus.fireEvent(new InfoEvent(msg.registrationSuccess(), InfoEvent.UserMessageType.SUCCESS));
                PlaceRequest req = new PlaceRequest(LoginPlace.NAME);
                eventBus.fireEvent(new PlaceRequestEvent(req));
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            Log.info("Registering an account went wrong...", throwable);
        }
    };

}
